#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <signal.h>
#include <errno.h>

#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "type.h"
#include "udp_net.h"
#include "debug.h"
#include "serial.h"
#include "pthread_pool.h"
#include "dbsync.h"

static standby_t gstandby_prarm;


#if 1
int dbsync_update_status(int role)
{
	int ret;
	void *res;

	pthread_mutex_lock(&lock);
	pre_role = cur_role;
	cur_role = role;
	pthread_mutex_unlock(&lock);

	/* [UNKNOWN | MASTER]->STANDBY, start server */
	if (pre_role != STANDBY && cur_role == STANDBY) {
		ret = dbsync_start_server();
	/* STANDBY->[UNKNOWN | MASTER], stop server */
	} else if (pre_role == STANDBY && cur_role != STANDBY) {
		ret = dbsync_stop_server();
	}

	return ret;
}

int dbsync_force_sync(const char *ip)
{
	int ret;
	int retry = 3;

	pthread_mutex_lock(&lock);
	if (cur_role != MASTER) {
		pthread_mutex_unlock(&lock);
		return -1;
	}
	pthread_mutex_unlock(&lock);
	while (retry > 0) {
		ret = dbsync_do_sync(ip, DB_FILE);
		if (ret == 0)
			return 0;
		sleep(1);
	}
}

int dbsync_set_maintain(const char *ip, int maintain)
{
	pthread_mutex_lock(&lock);
	pre_maintain = cur_maintain;
	cur_maintain = maintain;
	pthread_mutex_unlock(&lock);

	if (pre_maintain == 1 && cur_maintain == 0) {
		dbsync_force_sync(ip);
	}
}

static long systime(void)
{
    struct sysinfo info;
    sysinfo(&info);
    return info.uptime;
}

static int refresh_stainfo(int role)
{
    return dbsync_update_status(role);
}

static int standby_prarm_init(standby_t *pstandby_prarm)
{
    pstandby_prarm->net_port = NET_PORT;
    pstandby_prarm->thread_count = MAX_THREAD;
    pstandby_prarm->p_serial = SERIAL;
    pstandby_prarm->timer_first = FIRST_RUN;
    pstandby_prarm->timer_interval = FREQ_NANOSECS;
    pstandby_prarm->serial_fd = INVALID;
    pstandby_prarm->net_fd = INVALID;
    pstandby_prarm->heartbeat = systime();
    pstandby_prarm->id = 0;
    pstandby_prarm->role = UNKNOWN;

    return 0;
}





static int get_ip(char *ip)
{
    memcpy(ip, "192.168.2.5",sizeof("192.168.2.5"));
    return 0;
}

static int refresh_maintain(const char *ip)
{
    dbsync_force_sync(ip);
}


static int get_priority(void)
{

#if 0
    char buffer[1024];
    memset(buffer,0x0,sizeof(buffer));
    int fd = open("/tmp/testf",O_CREAT|O_RDWR);
    if (fd < 0)
        return -1;

    read(fd, buffer,sizeof(buffer));

    close(fd);

    int res = atoi(buffer);
    if (res < 0 )
        res = 0;

    printf("=================%d==========================\n",res);

    return 0;
#endif

}

static int refresh_my_role(standby_t *standby_prarm)
{
    int id = 0;
    id = hardware_get_cardid();
    if (id == standby_prarm->id)
    {
        if (standby_prarm->role != UNKNOWN)
            return 0;
    }

    if (id == 1)
    {
        standby_prarm->role = MASTER;
        standby_prarm->id = id;
        refresh_stainfo(standby_prarm->role);

        return 0;
    }
    else if (id > 1)
    {
    	if (standby_prarm->id == 1 && standby_prarm->role == MASTER)
    	{
        	standby_prarm->id = id;
        	return 1;
   	 }
    
    }

    standby_prarm->id = id;

    if (standby_prarm->online == ONLINE)
    {
        switch (standby_prarm->serial_status | standby_prarm->net_status)
        {
        case UNKNOWN:
            if (standby_prarm->role == UNKNOWN)
                break;

        case MASTER:
            if (standby_prarm->role == UNKNOWN)
	        {
            	standby_prarm->role = STANDBY;
	        }
            return 0;

        case STANDBY:
            if (standby_prarm->role = UNKNOWN)
	    {
		    standby_prarm->role = MASTER;
	    }

            return 0;
        }


    }

    switch (standby_prarm->id)
    {
    case 3:
        standby_prarm->role = MASTER;
        break;
    case 4:
        standby_prarm->role = STANDBY;
        break;

    }

    refresh_stainfo(standby_prarm->role);
    return 0;
}

static int msg_handle(int type,int mode, int arg, standby_t *standby_prarm)
{
    debug(DEBUG,__FUNCTION__,"msg type %x mode %x arg %d\n",type,mode,arg);
    switch (type)
    {
	    case HEARTBEAT:
	    {
	        standby_prarm->heartbeat = systime();
	        if(mode == UART_HEART_BEAT)
	        {
	            standby_prarm->serial_status = arg;
	        }
	        else if (mode == NET_HEART_BEAT)
	        {
	            standby_prarm->net_status = arg;
	        }
	        standby_prarm->online = ONLINE;
	        break;
	    }
       case REFRESH:
       default:
    	{
	        if (systime() - standby_prarm->heartbeat > OFFLINE_TIMEOUT)
	        {
	            standby_prarm->online = OFFLINE;
	            debug(ERROR,__FUNCTION__,"offline sysinfo.uptime %ld hearbeat %ld offline timeout %ld\n",systime(), ctx->heartbeat, OFFLINE_TIMEOUT);
	        }
			break;
    	}
    }

    return 0;
}


old_function()
{

			    //发出通知，我还没有角色
				refresh_stainfo(gstandby_prarm.role);
		        uart_init(gstandby_prarm);
		        net_init(gstandby_prarm);

		        net_heart_beat(gstandby_prarm);
		        serial_heart_beat(gstandby_prarm);
		        get_ip(gstandby_prarm->net_ip);

		        if (refresh_my_role(gstandby_prarm) == 1)
		        {
		            refresh_maintain(gstandby_prarm->net_ip);
		        }
		        refresh_stainfo(gstandby_prarm->role);
}

static void timer_handle(int sig, siginfo_t *info,void *context)
{
    msg_t *sigmsg = (void *)info->si_ptr;
    debug(DEBUG,__FUNCTION__,"signal %d, msg type %x mode %x arg %d\n",sig,sigmsg->type,sigmsg->mode,sigmsg->arg);
    msg_handle(sigmsg->type, sigmsg->mode, sigmsg->arg, &gstandby_prarm);
    return ;
}



int timer_init(void)
{
    struct sigaction act;
    timer_t timerid;
    struct sigevent sev;
    struct itimerspec its;
    sigset_t mask;

    msg_t timer_arg;
    timer_arg.type = REFRESH;
    timer_arg.mode = 0;
    timer_arg.arg = 0;

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIGRTMIN;
    sev.sigev_value.sival_ptr = &timer_arg;
    if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) == -1)
        debug(ERROR,__FUNCTION__,"timer_create:%s\n",strerror(errno));

    sigemptyset(&act.sa_mask);
    act.sa_sigaction = timer_handle;
    act.sa_flags = SA_SIGINFO;
	if (sigaction(SIGRTMIN,&act,NULL)<0)
    {
        debug(ERROR,__FUNCTION__,"sigaction:%s\n",strerror(errno));
        return -1;
    }

    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = gstandby_prarm.timer_first;
    its.it_interval.tv_sec = gstandby_prarm.timer_interval;
    its.it_interval.tv_nsec = 0;

    if (timer_settime(timerid, 0, &its, NULL) == -1)
    {
        debug(ERROR,__FUNCTION__,"timer_settime:%s\n",strerror(errno));
    }

}



#define SLOT_ONLINE_PIN_INIT 2
#define SLOT_ONLINE_PIN_HIGH 1
#define SLOT_ONLINE_PIN_LOW 0

#define SLOT_OFFLINE_STATUS  0
#define SLOT_ONLINE_STATUS   1
#define SLOT_INSERT_STATUS   2
#define SLOT_OUT_STATUS      3

int sigal_handle(void)
{
    int work_status = READ_SLOT_STATUS;
    switch(work_status)
    {
        case SLOT_OFFLINE_STATUS:
        {
            if()
            {
                work_status = READ_SLOT_STATUS;
            }
            else
            {
                work_status = HAND_SHAK_STATUS;
            }
            break;
        }
        case SLOT_ONLINE_STATUS:
        {
            work_status = HAND_SHAK_STATUS;
            break;
        }
        case SLOT_INSERT_STATUS:
        {
            if(net_online == NONAL)
            {
                //start db_sync
            }
            else
            {
                //stop db_sync
                work_status = READ_SLOT_STATUS;
            }
            work_status = HAND_SHAK_STATUS;
            break;
        }
        case SLOT_OUT_STATUS:
        {
        
            break;
        }
        default:
        {
        
            break;
        }

    }
}

int backup_role_exchange(void)
{


}

int gother_slot = 0;

int standby_start(void)
{
    int res = 0, my_cur_role, my_pre_role;
    pth_pool_t *t_pool = NULL;
    pth_pool_t *pt;

    memset(&gstandby_prarm, 0x0,sizeof(ctx_t));

    standby_prarm_init(&gstandby_prarm);
    if (pthread_pool_create(&t_pool, gstandby_prarm.thread_count) < 0)
    {
        debug(ERROR,__FUNCTION__,"pthread pool %s\n","error");
        return -1;
    }
    handshake_init(&gstandby_prarm);  //定时监听对方角色
    heartbeat_init(&gstandby_prarm);  //监听网络状态
	slot_init(&gstandby_prarm);       //持续监听对端卡槽状态
	judge_init(&gstandby_prarm);      //这是角色判断状态机

    while(1)
    {
        my_cur_role = judge_get_cur_my_role();
        if(my_cur_role == my_pre_role)
        {
            if()
            {


            }
            else
            {


            }

        }
        else
        {

           backup_role_exchange(my_cur_role);
        }
        my_pre_role = my_cur_role;

        sleep(1);
    }

    if (ctx.serial_fd != INVALID)
    {
        serial_close(ctx.serial_fd);
        ctx.serial_fd = INVALID;
    }

    if (ctx.net_fd != INVALID)
    {
        udp_destroy(ctx.net_fd);
        ctx.net_fd = INVALID;
    }
    thread_pool_destroy(t_pool);

    return 0;
}
#endif

